/*
* Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Camerality OpenGL rendering based view implementation.
*
*/

// INCLUDE FILES
#include <math.h>
#include <akndef.h>
#include "cameralitytraces.h"
#include "cameralityappui.h"
#include "cameralityglcontainer.h"
#include "cameralityviewfindercontainer.h"
#include "cameralityinfocontainer.h"
#include "cameralitycontainer.h"


// ================= MEMBER FUNCTIONS =======================

/*!
* Two-phased constructor.
* @return Container instance.
*/
CCameralityContainer* CCameralityContainer::NewL()
    {
    CCameralityContainer* self = new (ELeave) CCameralityContainer();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

/*!
* Constructor.
*/
CCameralityContainer::CCameralityContainer()
    {
    }

/*!
* Second phase constructor.
*/
void CCameralityContainer::ConstructL()
    {
    DoConstructL();
    HandleResourceChange(KEikDynamicLayoutVariantSwitch); // Leave place for soft buttons if needed
    }

/*!
* Destructor.
* Releases any used resources.
*/
CCameralityContainer::~CCameralityContainer()
    {
    TRACE_ENTER();
    delete iVfContainer;
    delete iGlContainer;
    delete iInfoContainer;
    TRACE_EXIT();
    }

/*!
* Show this control.
*/
void CCameralityContainer::Show(const TRect& extent)
    {    
    CCameralityBaseContainer::Show(extent);
    }

/*!
* Hide this control.
*/
void CCameralityContainer::Hide()
    {
    if (IsVisible())
        {
        StopAllActivity();        
        CCameralityBaseContainer::Hide();
        }
    }

/*!
* Called by framework when the view size is changed.
*/
void CCameralityContainer::SizeChanged()
    {
    TRACE_ENTER();
    TRect rect(CalculateRect());
   
    if (iInfoContainer && iInfoContainer->IsVisible())
        {
        TRACE("[Camerality] Resizing info container");
        iInfoContainer->SetRect(rect);        
        }
    if (iVfContainer && iVfContainer->IsVisible())
        {
        TRACE("[Camerality] Resizing viewfinder container");
        iVfContainer->SetRect(rect);
        }
    if (iGlContainer && iGlContainer->IsVisible())
        {
        TRACE("[Camerality] Resizing OpenGL container");
        iGlContainer->SetRect(rect);
        }
    TRACE_EXIT();
    }

/**
* Handles a change to the control's resources. This method
* reacts to the KEikDynamicLayoutVariantSwitch event (that notifies of
* screen size change) by calling the SetRect() or SetExtentToWholeScreen()
* again so  this control fills the new screen size. This will then trigger
* a call to the SizeChanged() method.
*
* @param aType Message UID value, only KEikDynamicLayoutVariantSwitch
* is handled by this method.
*/
void CCameralityContainer::HandleResourceChange(TInt aType)
    {
    switch (aType)
        {
        case KEikDynamicLayoutVariantSwitch:            
            TRACE("[Camerality] Using only part of screen.");
            TRect touchRect(0, 0, 
                            iAppUi->ClientRect().Width(), 
                            iAppUi->ClientRect().iTl.iY + iAppUi->ClientRect().Height());
            SetRect(touchRect); // Leave place for soft buttons
            break;
        }
    }

/*!
* Calculate rectangle for our container.
*/
TRect CCameralityContainer::CalculateRect()
    {
    TRACE_ENTER();
    
    TRect rect = iAppUi->ClientRect(); 
    TRACE_ARG("[Camerality] Calculated rect: tl:(%d,%d), size(%dx%d)", 
              rect.iTl.iX, rect.iTl.iY, rect.Width(), rect.Height());
    TRACE_EXIT();
    
    return rect;
    }

/*!
* Return number of controls inside this container.
*/
TInt CCameralityContainer::CountComponentControls() const
    {
    TInt count(0); 
    count += iVfContainer ? 1 : 0;
    count += iGlContainer ? 1 : 0;
    count += iInfoContainer ? 1: 0;
    return count;
    }

/*!
* Return CCoeControl inside this control with given index.
* Does nothing in this class.
* @param aIndex Index of the component control.
* @return Component control with given index, or NULL if index is not valid.
*/
CCoeControl* CCameralityContainer::ComponentControl(TInt aIndex) const
    {
    CCoeControl* containers[3];
    TInt index = 0;
    if (iVfContainer)
        {
        containers[index++] = iVfContainer;
        }
    if (iGlContainer)
        {
        containers[index++] = iGlContainer;
        }
    if (iInfoContainer)
        {
        containers[index++] = iInfoContainer;
        }
    
    if (aIndex < index) 
        {
        return containers[aIndex];
        } 
    else 
        {
        return NULL;
        }
    }

/*!
* Normal CCoeControl drawing method.
*/
void CCameralityContainer::Draw(const TRect& /*aRect*/) const
    {
    TRACE_ENTER();
    CWindowGc& gc = SystemGc();
    gc.SetPenStyle(CGraphicsContext::ENullPen);
    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.SetBrushColor(KRgbGray);
    gc.DrawRect(Rect());
    TRACE_EXIT();
    }

/*!
* Method from MCoeControlObserver that handles an event from the observed control.
* Does nothing in this implementation.
* @param aControl   Control changing its state.
* @param aEventType Type of the control event.
*/

void CCameralityContainer::HandleControlEventL(CCoeControl* /*aControl*/, TCoeEvent /*aEventType*/)
    {
    // TODO: Add any control event handler code here
    }

/*!
* Start and show the viewfinder.
*/
void CCameralityContainer::StartViewfinderL()
    {
    if (!iVfContainer) 
        {
        iVfContainer = CCameralityViewfinderContainer::NewL();
        }
    
    TRect vfRect(CalculateRect());
    iVfContainer->Show(vfRect);

    AdjustOrdinals();
    }

/*!
* Stop and hide the viewfinder.
*/
void CCameralityContainer::StopViewfinder()
    {
    if (iVfContainer)
        {
        iVfContainer->Hide();
        }
    }

/*!
* Start and show OpenGL animation.
*/
void CCameralityContainer::StartAnimationL()
    {
    if (!iGlContainer)
        {
        iGlContainer = CCameralityGLContainer::NewL();        
        }

    TRect rect(CalculateRect());
    iGlContainer->Show(rect);

    AdjustOrdinals();
    }

/*!
* Stop and hide the OpenGL animation.
*/
void CCameralityContainer::StopAnimation()
    {
    if (iGlContainer)
        {
        iGlContainer->Hide();
        // Deleting the whole container to avoid problems
        // with background transparency when re-shown.
        delete iGlContainer;
        iGlContainer = NULL;
        }
    }

/*!
* Start GPU resource profiling and show some info
* on top of the rest of the UI.
*/
void CCameralityContainer::StartProfilingL()
    {
    if (!iInfoContainer)
        {
        iInfoContainer = CCameralityInfoContainer::NewL();
        }

    TRect rect(CalculateRect());
    iInfoContainer->Show(rect);
    AdjustOrdinals();
    }

/*!
* Stop GPU resource profiling.
*/
void CCameralityContainer::StopProfiling()
    {
    if (iInfoContainer)
        {
        iInfoContainer->Hide();
        }
    }


void CCameralityContainer::StartAllActivityL()
    {
    StartViewfinderL();     
    StartAnimationL();
    StartProfilingL();
         
    }

/*!
* Stop all activities: viewfinder, animation and profiling.
* Used when other application gets focus.
* If the application is not full screen (e.g. task switcher),
* we need this container for drawing the client area, so just
* hide the subcontainers to free resources for the other app.
*/
void CCameralityContainer::StopAllActivity()
    {
    StopProfiling();
    StopAnimation();
    StopViewfinder();    
    }

/*!
* Make sure our containers keep in the right order whenever
* we show or hide one of them. The order is always (from bottom to top)
* main container - viewfinder - animation - info.
*/
void CCameralityContainer::AdjustOrdinals()
    {
    if (iVfContainer && iVfContainer->IsVisible())           
        iVfContainer->Raise();
    if (iGlContainer && iGlContainer->IsVisible())   
        iGlContainer->Raise();
    if (iInfoContainer && iInfoContainer->IsVisible())   
        iInfoContainer->Raise();
    Window().SetOrdinalPosition(-1);
    }
// End of File
